/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.generic_return_type;

import picounit.features.base.Caller;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

class DefaultCheckCastRegistry implements CheckCastRegistry {
	private final Set<String> classesWithCasts = new HashSet<String>();
	private final Map<String, Casts> checkCasts = new HashMap<String, Casts>();

	///////////////////////////////////////////////////////////////////////////////////////////////
	// CheckCastRegistry methods
	///////////////////////////////////////////////////////////////////////////////////////////////

	public void addCheckCast(String className, String methodName, int line, String castTo) {
		System.out.println("addCheckCast(" + className + ", " + methodName + ", " + line + ", " + castTo + ")");

		getOrCreateCasts(className, methodName)
			.addCastByLineNumber(line, castTo);
	}

	public Cast getCast(Caller caller) {
		return getCasts(caller).getCastForLine(caller.lineNumber());
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// Implementation methods
	///////////////////////////////////////////////////////////////////////////////////////////////

	private Casts getCasts(Caller caller) {
		return getCasts(caller.className(), caller.methodName());
	}

	public Casts getCasts(String className, String methodName) {
		String key = buildKey(className, methodName);

		return checkCasts.containsKey(key) ? checkCasts.get(key) : Casts.NULL;
	}
	
	private Casts getOrCreateCasts(String className, String methodName) {
		return haveCasts(className, methodName) ? getCasts(className, methodName)
			: addCasts(className, methodName);
	}

	private boolean haveCasts(String className, String methodName) {
		return containsCastsForClass(className) && 
			checkCasts.containsKey(buildKey(className, methodName));
	}

	private String buildKey(String className, String methodName) {
		return className + "." + methodName;
	}

	private Casts addCasts(String className, String methodName) {
		Casts casts = new Casts();

		classesWithCasts.add(className);
		checkCasts.put(buildKey(className, methodName), casts);

		return casts;
	}

	private boolean containsCastsForClass(String className) {
		return classesWithCasts.contains(className);
	}
}
